#include "model.h"

#include "tracer/wave_tracer.h"
#include "cpu/difftest.h"   
#include "memory/mem.h"
#include "cpu/cpu.h"
#include "ioe/ioe.h"
#include "device/device.h"
#include "utils/systime.h"

void sdb_mainloop();
void reset();
void init_sim();
void init_monitor(int, char *[]);

uint64_t *gpr;
Vtop *top;
bool sim_finish = false;
bool silent = false;
bool continue_flag = false;
uint32_t inst_cnt = 0;

static int ret_val = 1;
int main(int argc, char **argv)
{
    init_monitor(argc, argv);
    init_sim();
    Log("sim start");
    uint64_t t1,t2;
    t1 = SYS_GetTicks();
    sdb_mainloop();
    t2 = SYS_GetTicks();
    Log("sim end");
    uint64_t used_ms = (t2 - t1)/1000;
    printf("sim inst count %d cycles:%d speed %.0f inst/s %.0fcycles/s\n",inst_cnt,total_cycles,inst_cnt*1000.0f/used_ms,total_cycles*1000.0f/used_ms);
    printf("performance: IPC: %.03f\n",(float)inst_cnt/total_cycles);
    IFONE(CONFIG_CACHE_COUNT, print_cache_count());
    print_busy_count();
    IFONE(CONFIG_WAVE_TRACE, deinit_wave_tracer());
    delete top;
    return ret_val;
}
void init_sim()
{
    top = new Vtop;
    gpr = top->GPR;
    IFONE(CONFIG_WAVE_TRACE, init_wave_tracer("wave_top.vcd"));
    reset();
}

void reset() {
    top->rst = 1;
    top->eval();
    for (int i = 0; i < 5; i++)
    {
        top->clk = 0;
        top->eval();
        top->clk = 1;
        top->eval();
    }
    top->rst = 0;
    top->eval();
}

extern "C" void other_inst(svBit ecall, svBit fence, svBit ebreak) {
    if(ebreak) {
        printf( (gpr[10] == 0) ? ANSI_FMT("HIT GOOD TRAP\n", ANSI_FG_GREEN) :
            ANSI_FMT("HIT BAD TRAP\n", ANSI_FG_RED));
        sim_finish = true;
        ret_val = gpr[10];
    }
}
